from win32com.client import Dispatch as dispatch_api
import numpy as np
import matplotlib.pyplot as plt
import math
import os
import sys
import re

def msd(l):
    lst=[]
    for i in l:
        if type(i) in (int,float):
            lst.append(i)
    n=float(len(lst))
    if n<=1: return 0,0
    mean=sum(lst)/n
    s=0
    for i in lst:
       s+=((i-mean)**2)
    sd=math.sqrt((1./(n-1))*s)
    return  mean,sd

def parse_log(filename):
    d={}
    it=[]
    v={}
    l=open(filename).readlines()
    flag=0
    for i in l:
        if i[:2]=="/*":
            flag+=1
            continue
        if i[:2]=="*/":
            flag-=1
            continue
        if flag>0: continue
        if i[0]=='-':continue
        p=i.split(':')
        if len(p)==2:
            d[p[0].strip()]=p[1].strip()
        elif len(p)==3:
            d[p[0].strip()]=p[2].strip()
        else:
            p=i.split('=')
            if len(p)>1:
                v[p[0].strip()]=p[1].strip()
            else:
                it.append(i.strip().split())
                
    return d,it,v

def plot():
    d,it,v=parse_log(r'D:\at\HarmonySearch\HarmonyGrayCoded_test\Harmony_GrayCoded_004.012')
#    x=[round(float(i)/1000) for i,j,k in it]
    x=[float(i) for i,j,k in it]
    y1=[float(j) for i,j,k in it]
    y2=[float(k) for i,j,k in it]
    a=np.arange(0,x[-1]+2,1000)
    b=np.interp(a,x,y2)
    a/=100
#    plt.plot(x,y1)
    x=np.log10(x)
    plt.plot(x,y2)
#    plt.plot(a,b)
    plt.title(r'$f_{3}(\overrightarrow{x})=\sum_{i=1}^{10}(x_{i}^{2}-10cos(2\pi x_{i})+10)$')
    plt.xlabel('Log(Iterations)')
    plt.ylabel('Euclidean Distance')
    yp=600
    for i in d:
        plt.text(2,yp,"%s: %s" % (i,d[i]))
        yp-=30
    plt.show()

def analyze_one(filename):
    d,it,v=parse_log(filename)

def find_events_in_list(st,dist):
    l=[]
    e=1
    for i in range(1,11):
        n=0
        e*=.1
        flag=0
        for j in dist:
            if j<e:
                l.append(st[n])
                flag=1
                break
            n+=1
        if flag==0:
            l.append("")
    return l

def find_dist_events(it):
    st=[int(i) for i,j,k in it]
    fit=[float(j) for i,j,k in it]
    dist=[float(k) for i,j,k in it]
    return find_events_in_list(st,dist)

def find_dist_events_in_log(filename):
    d,it,v=parse_log(filename)
    return find_dist_events(it)
    
def get_batch_files_list(path,filename_pat):
    pat=re.compile(filename_pat)
    l=[]
    for i in os.listdir(path):
        if pat.match(i):
            l.append(os.path.join(path,i))
    return l

def sigma_test(lstMSDEvents,lstFiles,s=3):
    lstNotPassedCounter=[0]*6      # one for each precsion form 0.1 to 1e-10
    for filename in lstFiles:
        lstLogEvents=find_dist_events_in_log(filename)
        for precision in range(6):
            l=lstMSDEvents[precision][0]-s*lstMSDEvents[precision][1]
            u=lstMSDEvents[precision][0]+s*lstMSDEvents[precision][1]
            if lstLogEvents[precision]<l or lstLogEvents[precision]>u:
                lstNotPassedCounter[precision]+=1
    return lstNotPassedCounter


def find_dist_events_in_batch(lstFiles):
    lstBatchEvents=[]
    for i in range(6):
        lstBatchEvents.append([])
    r=[]
    for filename in lstFiles:
        lstLogEvents=find_dist_events_in_log(filename)
        for precision in range(6):
            lstBatchEvents[precision].append(lstLogEvents[precision])
    for lstPrecsion in lstBatchEvents:
        r.append(msd(lstPrecsion))
    return r


def analyze_batch(path,filename_pat):
    lstFilenames=get_batch_files_list(path,filename_pat)
    lstMSDEvents=find_dist_events_in_batch(lstFilenames)
    lstMeanOfEvents=[int(round(i)) for i,j in lstMSDEvents]
    s1=max(sigma_test(lstMSDEvents,lstFilenames,1))
    s2=max(sigma_test(lstMSDEvents,lstFilenames,2))
    s3=max(sigma_test(lstMSDEvents,lstFilenames,3))
    return lstMeanOfEvents,(s1,s2,s3)


def batch_excel(path):
    lstFiles=os.listdir(path)
    lstFiles=[os.path.join(path,i) for i in lstFiles]
    R=0
    for file in lstFiles:
        R+=1
        C=3
        d,it,v=parse_log(file)
        l=d.keys()
        l.sort()
        r=1
        for i in l:
            o.Cells(r,1).value=i
            o.Cells(r,2).value=d[i]
            r+=1
        e=find_dist_events(it)
        o.Cells(R,C).value=R
        for i in e:
            C+=1
            o.Cells(R,C).value=i
            
algorithms=['derc_01', 'derc_02', 'derc_03', 'gabc', 'gagc', 'hsbc', 'hsgc', 'hsrc']
evals=[10,10,10,100,100,20,20,20]
testfn=['Rastrigin','Sphere','SchafferF6','Rosenbrock','Griewangk']
root=r'D:\Master\hg\lab\results'
def analyze_results(root):
    lstDir=[]
    d={}
    for i in algorithms:
        d[i]={}
        for j in testfn:
            directory= "%s\\%s\\%s" % (root,i,j)
            print directory
            lstFiles=os.listdir(directory)
            lstFiles=[os.path.join(directory,k) for k in lstFiles]
            lstMSDEvents=find_dist_events_in_batch(lstFiles)
            lstMeanOfEvents=[int(round(k)) for k,m in lstMSDEvents]
            d[i][j]=lstMeanOfEvents
    return d

def rp123(d,p):
    for i,j in zip(algorithms,evals):
        mul[i]=j
    g={}
    l=[]
    for i in algorithms:
        g[i]={}
        t=[]
        for j in testfn:
            t.append(d[i][j][p]*mul[i])
#            g[i][j]=[k*mul[i] for k in d[i][j]]
#            g[i][j]=d[i][j][p]*mul[i]
        l.append(t)
    return l

def table2excel(l):
    r=1
    c=1
    o = dispatch_api("Excel.Application")
    for i in l:
        r=r+1
        c=1
        for j in i:
            c=c+1
            o.cells(r,c).value=j
            
def main():
#    analyze_results(r'D:\Master\hg\lab\results')
    pass
    
if __name__ == "__main__":
##    fn=r'D:\Master\workbench\GO_Compare\123\001\GA_BC_01.001.gabc'
##    fn=r'D:\Master\workbench\GO_Compare\123\002\GA_BC_01.001.gabc'
##    fn=r'D:\Master\workbench\GO_Compare\123\003\GA_BC_01.001.gabc'
##    fn=r'D:\Master\workbench\GO_Compare\123\004\GA_BC_01.002.gabc'
###    d,it,v=parse_log(fn)
##    pat="GA_BC_01.\d\d\d.gabc"
##    path=r'D:\Master\workbench\GO_Compare\123\004'
###    r=analyze_batch(path,pat)
    main()

